#pragma once
#ifndef __SPORTS_MODE_INTERNAL_H__
#define __SPORTS_MODE_INTERNAL_H__
#include <sports_mode_cfg.h>
#include <stdint.h>
#include <bit_func.h>
#include <nrf_drv_rng.h>
#include <platform_toolchain.h>
#include <sports_mode_common.h>
#include <sports_mode_store.h>
//#include <sports_mode_vtbl.h>
// #define SPORTS_MODE_HEART_RATE_MAX_COUNT (SPORTS_MODE_STORE_INTERVAL_SECONDS / SPORTS_MODE_HEART_RATE_COLLECT_INTERVAL_SECONDS)
// #ifdef SPORTS_MODE_HAS_GPS
// #define SPORTS_MODE_GPS_MAX_COUNT (SPORTS_MODE_STORE_INTERVAL_SECONDS / SPORTS_MODE_GPS_COLLECT_INTERVAL_SECONDS)
// #define SPORTS_MODE_SPEED_MAX_COUNT (SPORTS_MODE_STORE_INTERVAL_SECONDS / SPORTS_MODE_GPS_COLLECT_INTERVAL_SECONDS)
//#endif //!<#ifdef SPORTS_MODE_HAS_GPS
//#define SPORTS_MODE_ID_LEN (4)

typedef struct __sports_mode_runtime_info_t
{
    uint32_t detail_collect_index; //!< 采集后存放在数组的哪个位置
    uint32_t total_steps;          //!< 开始运动时，step是多少
    uint32_t last_steps;
    uint32_t steps_add_for_freq; //!< 用于计算步频
    uint32_t hr_not_wear_time;   //!< 心率未佩戴时间
    uint32_t add_active;
    uint32_t total_active;
    uint32_t last_active;
    uint32_t current_steps_freq; //当前步频 0.01,放大了100倍
    uint16_t current_speed;      //当前速度-cm/s
    uint32_t hr_total;
    uint32_t hr_count;
    uint16_t heart_rate_level_0_seconds;
#ifdef SPORTS_MODE_HAS_GPS
    float altitude_total; //!< 海拔总额
    float last_altitude;
    uint32_t speed_total;
    uint32_t effective_time;
#endif //!< SPORTS_MODE_HAS_GPS
} sports_mode_runtime_info_t;

#ifdef SPORTS_MODE_CHECK
extern volatile int read_cnt;
extern volatile int write_cnt;
#endif
typedef struct __sports_mode_instance_t
{
    sports_mode_state_t state; //!< sports_mode_state_t
    void *vptr;
    sports_mode_id_t id;
    sports_mode_summary_info_t summary_info;
    sports_mode_runtime_info_t runtime_info;
    sports_mode_detail_t detail_info[SPORTS_MODE_DETAIL_CACHE_COUNT];
} sports_mode_instance_t;
extern uint32_t sports_mode_calorie;
extern uint32_t sports_mode_distance;

PLATFORM_FORCEINLINE void sports_mode_calculation_calorie_distance(void)
{
    sports_mode_store_calculation_calorie_distance();
}

extern sports_mode_instance_t sports_mode_instance;

/**
 * @brief 内部接口，表明当前函数只会尝试从结构体里读数据
 *        只可能在定时器（中断）及主循环（非中断）下进行相关操作，如果在主循环里检测lock_cnt 不为0，那说明已经出错了
 *
 */
PLATFORM_FORCEINLINE void internal_sports_mode_read_start(void)
{
#ifdef SPORTS_MODE_CHECK
    if (!is_isr_mode())
    {
        Expects(read_cnt == 0 && write_cnt == 0);
    }
    read_cnt++;
#endif //!<#ifdef SPORTS_MODE_CHECK
}

/**
 * @brief 内部接口，表明当前函数只会尝试从结构体里读数据
 *
 */
PLATFORM_FORCEINLINE void internal_sports_mode_read_end(void)
{
#ifdef SPORTS_MODE_CHECK
    read_cnt--;
#endif //!<#ifdef SPORTS_MODE_CHECK
}
/**
 * @brief 内部接口，表明当前函数会尝试从结构体里读写数据
 *        只可能在定时器（中断）及主循环（非中断）下进行相关操作，如果在主循环里检测lock_cnt 不为0，那说明已经出错了
 *
 */
PLATFORM_FORCEINLINE void internal_sports_mode_write_start(void)
{
#ifdef SPORTS_MODE_CHECK
    if (!is_isr_mode())
    {
        Expects(read_cnt == 0 && write_cnt == 0);
    }
    write_cnt++;
#endif //!<#ifdef SPORTS_MODE_CHECK
}
/**
 * @brief 内部接口，表明当前函数会尝试从结构体里读写数据
 *
 */
PLATFORM_FORCEINLINE void internal_sports_mode_write_end(void)
{
#ifdef SPORTS_MODE_CHECK
    write_cnt--;
#endif //!<#ifdef SPORTS_MODE_CHECK
}

/**
 * @brief 内部接口，没有额外检测
 *
 * @return true
 * @return false
 */
PLATFORM_FORCEINLINE bool internal_sports_mode_is_idle(void)
{
    return sports_mode_instance.state == sports_mode_state_idle;
}

PLATFORM_FORCEINLINE bool sports_mode_is_idle(void)
{
    internal_sports_mode_read_start();
    bool result = internal_sports_mode_is_idle();
    internal_sports_mode_read_end();
    return result;
}

/**
 * @brief 内部接口，没有额外检测
 *
 * @return true
 * @return false
 */
PLATFORM_FORCEINLINE int internal_sports_mode_get_state(void)
{
    return sports_mode_instance.state;
}

/**
 * @brief
 *
 * @return int sports_mode_state_t
 */
PLATFORM_FORCEINLINE int sports_mode_get_state(void)
{
    internal_sports_mode_read_start();
    int result = internal_sports_mode_get_state();
    internal_sports_mode_read_end();
    return result;
}
/**
 * @brief 内部接口，没有额外检测
 *
 * @return sports_mode_mode_t
 */
PLATFORM_FORCEINLINE sports_mode_mode_t internal_sports_mode_get_now_mode(void)
{
    {
        // Ensures(sports_mode_instance.summary_info.mode >= sports_mode_mode_start && sports_mode_instance.summary_info.mode < sports_mode_mode_end);
        return (sports_mode_mode_t)(sports_mode_instance.summary_info.mode);
    }
}
PLATFORM_FORCEINLINE sports_mode_mode_t sports_mode_get_now_mode(void)
{
    //       #warning debug
    //       return sports_mode_mode_walk;
    sports_mode_mode_t result = sports_mode_mode_invalid;
    internal_sports_mode_read_start();
    result = internal_sports_mode_get_now_mode();
    internal_sports_mode_read_end();
    return result;
}

PLATFORM_FORCEINLINE int32_t sports_mode_get_sports_duration(void)
{
    int32_t result = 0;
    internal_sports_mode_read_start();
    result = sports_mode_instance.summary_info.duration;
    internal_sports_mode_read_end();
    return result;
}

PLATFORM_FORCEINLINE uint32_t sports_mode_get_sports_start_time(void)
{
    int32_t result = 0;
    internal_sports_mode_read_start();
    result = sports_mode_instance.summary_info.start_time;
    internal_sports_mode_read_end();
    return result;
}

PLATFORM_FORCEINLINE int32_t sports_mode_get_sports_pause_time(void)
{
    int32_t result = 0;
    internal_sports_mode_read_start();
    result = sports_mode_instance.summary_info.pause_time;
    internal_sports_mode_read_end();
    return result;
}

/**
 * @brief
 *
 * @return uint32_t 单位小卡
 */
PLATFORM_FORCEINLINE uint32_t sports_mode_get_sports_calorie(void)
{
    uint32_t result = 0;
    internal_sports_mode_read_start();
    result = sports_mode_instance.summary_info.calorie;
    internal_sports_mode_read_end();
    return result;
}

/**
 * @brief
 *
 * @return uint32_t 单位米
 */
PLATFORM_FORCEINLINE uint32_t sports_mode_get_sports_mileage(void)
{
    uint32_t result = 0;
    internal_sports_mode_read_start();
    result = sports_mode_instance.summary_info.mileage;
    internal_sports_mode_read_end();
    return result;
}

/**
 * @brief
 *
 * @return uint32_t 当前速度 cm/s
 */
PLATFORM_FORCEINLINE uint32_t sports_mode_get_sports_current_speed(void)
{
    uint32_t result = 0;
    internal_sports_mode_read_start();
    result = sports_mode_instance.runtime_info.current_speed;
    internal_sports_mode_read_end();
    return result;
}

/**
 * @brief
 *
 * @return uint32_t 步
 */
PLATFORM_FORCEINLINE uint32_t sports_mode_get_sports_steps(void)
{
    uint32_t result = 0;
    internal_sports_mode_read_start();
    result = sports_mode_instance.runtime_info.total_steps;
    internal_sports_mode_read_end();
    return result;
}
/**
 * @brief
 *
 * @return uint32_t 步
 */
PLATFORM_FORCEINLINE uint32_t sports_mode_get_sports_end_steps(void)
{
    uint32_t result = 0;
    internal_sports_mode_read_start();
    result = sports_mode_instance.summary_info.average_pitch * sports_mode_instance.summary_info.duration / 60;
    internal_sports_mode_read_end();
    return result;
}

/**
 * @brief
 *
 * @return uint32_t 步
 */
PLATFORM_FORCEINLINE uint32_t sports_mode_get_sports_current_steps_freq(void)
{
    uint32_t result = 0;
    internal_sports_mode_read_start();
    result = sports_mode_instance.runtime_info.current_steps_freq;
    internal_sports_mode_read_end();
    return result;
}
/**
 * @brief
 *
 * @return uint32_t 步
 */
PLATFORM_FORCEINLINE uint32_t sports_mode_get_sports_steps_freq(void)
{
    uint32_t result = 0;
    internal_sports_mode_read_start();
    result = sports_mode_instance.summary_info.average_pitch;
    internal_sports_mode_read_end();
    return result;
}
/**
 * @brief
 *
 * @return uint8_t
 */
PLATFORM_FORCEINLINE uint8_t sports_mode_get_sports_minimal_heart_rate(void)
{
    uint8_t result = 0;
    internal_sports_mode_read_start();
    result = sports_mode_instance.summary_info.minimal_heart_rate;
    internal_sports_mode_read_end();
    return result;
}
PLATFORM_FORCEINLINE uint16_t sports_mode_get_sports_heart_rate_level_seconds(int level)
{
    uint16_t result = 0;
    internal_sports_mode_read_start();
    switch (level)
    {
    case 0:
        result = sports_mode_instance.runtime_info.heart_rate_level_0_seconds;
        break;
    case 1:
        result = sports_mode_instance.summary_info.heart_rate_level_1_seconds;
        break;
    case 2:
        result = sports_mode_instance.summary_info.heart_rate_level_2_seconds;
        break;
    case 3:
        result = sports_mode_instance.summary_info.heart_rate_level_3_seconds;
        break;
    case 4:
        result = sports_mode_instance.summary_info.heart_rate_level_4_seconds;
        break;
    case 5:
        result = sports_mode_instance.summary_info.heart_rate_level_5_seconds;
        break;
    }
    internal_sports_mode_read_end();
    return result;
}
/**
 * @brief
 *
 * @return uint8_t
 */
PLATFORM_FORCEINLINE uint8_t sports_mode_get_sports_maximum_heart_rate(void)
{
    uint8_t result = 0;
    internal_sports_mode_read_start();
    result = sports_mode_instance.summary_info.maximum_heart_rate;
    internal_sports_mode_read_end();
    return result;
}
/**
 * @brief
 *
 * @return uint8_t
 */
PLATFORM_FORCEINLINE uint8_t sports_mode_get_sports_avg_heart_rate(void)
{
    uint8_t result = 0;
    internal_sports_mode_read_start();
    result = sports_mode_instance.summary_info.average_heart_rate;
    internal_sports_mode_read_end();
    return result;
}
/**
 * @brief 定时器回调
 *
 */
void sports_mode_timeout(void);

/**
 * @brief
 *
 * @return uint32_t
 */
PLATFORM_FORCEINLINE uint32_t sports_mode_get_distance(void)
{
    return sports_mode_distance;
}
/**
 * @brief 获取运动模式今天增加了多少卡路里
 *
 * @return uint32_t
 */
PLATFORM_FORCEINLINE uint32_t sports_mode_get_calorie(void)
{
    return sports_mode_calorie;
}

/**
 * @brief 初始化存储
 *
 */
PLATFORM_FORCEINLINE void sports_mode_ctor(void)
{
    sports_mode_store_ctor();
}

/**
 * @brief 清除flash所有数据
 *
 */
PLATFORM_FORCEINLINE void sports_mode_clear(void)
{
    sports_mode_store_clear_force();
}

/**
 * @brief
 *
 * @return uint32_t cm
 */
PLATFORM_FORCEINLINE uint32_t sports_mode_get_accumulated_climbing(void)
{
    return sports_mode_instance.summary_info.accumulated_climbing;
}
/**
 * @brief
 *
 * @return uint32_t cm
 */
PLATFORM_FORCEINLINE uint32_t sports_mode_get_accumulated_downhill(void)
{
    return sports_mode_instance.summary_info.accumulated_downhill;
}

/**
 * @brief
 *
 * @return uint32_t
 */
PLATFORM_FORCEINLINE uint32_t sports_mode_get_avg_speed(void)
{
    return sports_mode_instance.summary_info.average_speed;
}
/**
 * @brief
 *
 * @return uint32_t
 */
PLATFORM_FORCEINLINE uint32_t sports_mode_get_maximum_speed(void)
{
    return sports_mode_instance.summary_info.maximum_speed;
}

/**
 * @brief
 *
 * @return uint32_t
 */
PLATFORM_FORCEINLINE int32_t sports_mode_get_avg_altitude(void)
{
    return sports_mode_instance.summary_info.average_altitude;
}
#endif //!<#ifndef __SPORTS_MODE_INTERNAL_H__
